Skip to main content

Composition vs Inheritance

Composition vs Inheritance in Java (HAS-A vs IS-A)​

Why This File Exists​

Inheritance is often overused when composition is the better choice.

This file explains:

  • Difference between IS-A and HAS-A
  • Why composition is preferred in modern Java design
  • How poor inheritance creates fragile systems
  • Practical rules to choose correctly

This topic separates average developers from good designers.


The Core Difference (One Line)​

  • Inheritance → IS-A relationship
  • Composition → HAS-A relationship

Choosing the wrong one leads to tight coupling and bugs.


Inheritance (Quick Recap)​

Inheritance means:

class Dog extends Animal { }

Dog is an Animal.

Characteristics:

  • Strong coupling
  • Behavior inherited automatically
  • Changes in parent affect child

Composition (What It Means)​

Composition means:

class Car {
private Engine engine;
}

Car has an Engine.

Characteristics:

  • Loose coupling
  • Behavior delegated, not inherited
  • Easy to change implementation

Why Composition Is Preferred​

Composition:

  • avoids fragile hierarchies
  • allows runtime flexibility
  • limits change impact
  • supports better testing

Inheritance:

  • locks behavior at compile time
  • spreads changes unintentionally
  • is harder to refactor

Example: Bad Inheritance​

class Bird {
void fly() {}
}

class Penguin extends Bird {
}

Problem:

  • Penguin cannot fly
  • IS-A relationship is broken

Same Example Using Composition​

interface FlyBehavior {
void fly();
}

class Bird {
private FlyBehavior flyBehavior;
}

Now:

  • Flying is optional
  • Behavior can vary per bird

Tight Coupling Problem​

Inheritance creates:

  • dependency on parent implementation
  • difficulty in changing behavior
  • ripple effects

Composition avoids this by delegation.


When Inheritance Is Acceptable​

Use inheritance when:

  • IS-A relationship is true
  • behavior is stable
  • hierarchy is shallow
  • parent is designed for extension

Examples:

  • Exception hierarchy
  • Collection framework

When Composition Is Better​

Use composition when:

  • behavior varies
  • runtime flexibility is needed
  • change is expected
  • reuse is the only goal

Modern Java favors composition.


Composition + Interfaces (Best Combo)​

class Service {
private Logger logger;
}
  • Depends on interface
  • Implementation can change
  • Follows Dependency Inversion

Common Mistakes​

  • Using inheritance for reuse only
  • Deep inheritance hierarchies
  • Ignoring IS-A rule
  • Fear of composition

Best Practices​

  • Prefer composition over inheritance
  • Validate IS-A relationship strictly
  • Keep inheritance hierarchies shallow
  • Use interfaces for composition

Interview Notes​

  • Difference between composition and inheritance
  • HAS-A vs IS-A
  • Why composition is preferred
  • Real-world examples
  • When inheritance is justified

Summary​

Inheritance couples. Composition composes.

Good design chooses composition by default, and inheritance only when truly needed.